package fr.bda.cloud.data;

import java.util.ArrayList;
import java.util.List;

/**
 * This class represent a data save in the cloud
 * 
 * @author BARET
 * @since 21/10/2012
 */
public class Data {


	/** The blocs of the file */
	protected List<Bloc> blocs = new ArrayList<>();

	/** The number of blocs */
	private int nbBlocs;

	/** The parity block */
	protected Bloc parityBloc;

	public Data(int nbBlocs) {
		this.nbBlocs = nbBlocs;
		blocs.clear();
	}

	public Data(int nbBlocs, byte[] bytes) {
		this.nbBlocs = nbBlocs;
		blocs.clear();
		blocs.addAll(buildBlocList(bytes, nbBlocs));
		parityBloc = buildBlocParity(blocs);
	}

	/**
	 * To split a string into N blocs
	 * 
	 * @param content
	 *            The content to split
	 * @param nbBloc
	 *            The number of bloc to create
	 * @return The Bloc create from the content
	 */
	public static List<Bloc> buildBlocList(byte[] content, int nbBloc) {

		// The bloc list to create
		List<Bloc> blocs = new ArrayList<>();

		// Get the content length
		int contentLength = content.length;

		// Evaluate the size bloc
		int blocSize = contentLength / nbBloc;
		if (contentLength % nbBloc > 0) {
			blocSize++;
		}

		// Initialize bloc objects
		for (int i = 0; i < nbBloc; i++) {
			Bloc b = new Bloc(blocSize);
			blocs.add(b);
		}

		// Initialize the bloc values
		int indD = 0;
		int length = blocSize;
		for (int i = 0; i < nbBloc && indD < contentLength; i++) {

			byte[] data = new byte[length];
			System.arraycopy(content, indD, data, 0, length);
			blocs.get(i).setData(data);

			indD = indD + length;
			length = contentLength - indD;
			if (length > blocSize) {
				length = blocSize;
			}
		}
		return blocs;
	}

	public static String xorString(String s1, String s2) {

		byte b1[] = s1.getBytes();
		byte b2[] = s2.getBytes();

		int len = (b1.length > b2.length) ? b1.length : b2.length;
		byte res[] = new byte[len];

		for (int i = 0; i < len; i++) {
			if (i < b1.length) {
				if (i < b2.length) {
					res[i] = (byte) (b1[i] ^ b2[i]);
				} else {
					res[i] = (byte) (b1[i] ^ 0);
				}
			} else {
				res[i] = (byte) (0 ^ b2[i]);
			}
		}

		return new String(res);
	}

	public static Bloc buildBlocParity(List<Bloc> blocs) {
		Bloc parityBloc = null;
		if (blocs.size() > 0) {
			parityBloc = new Bloc(blocs.get(0).getData());
			for (int i = 1; i < blocs.size(); i++) {
				parityBloc = parityBloc.xor(blocs.get(i));
			}
		}
		return parityBloc;
	}

	public static Bloc buildBlocData(List<Bloc> blocs, Bloc parityBloc) {

		Bloc dataBloc = new Bloc(parityBloc.getData());

		if (blocs.size() > 0) {
			for (int i = 0; i < blocs.size(); i++) {
				dataBloc = dataBloc.xor(blocs.get(i));
			}
		}
		return dataBloc;
	}

	public int getNbBlocs() {
		return nbBlocs;
	}
}
